{
 "cells": [
  {
   "cell_type": "markdown",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "主成分分析PCA(Principal Component Analysis):\n",
    "+ 数据压缩\n",
    "+ 数据可视化\n",
    "+ 降维分析：第一个主成分就是从数据差异性最大(方差最大)的方向提取出来的，<br>\n",
    "第二个主成分则来自于数据差异性次大的方向，并且要与第一个主成分方向正交。\n",
    "\n",
    "算法步骤\n",
    "+ 1.数据预处理：中心化$X-\\overline{X}$。\n",
    "+ 2.求样本的协方差矩阵$\\frac{1}{m}XX^T$\n",
    "+ 3.对协方差$\\frac{1}{m}XX^T$矩阵做特征值分解。\n",
    "+ 4.选出最大的k个特征值对应的k个特征向量。\n",
    "+ 5.将原始数据投影到选取的特征向量上。\n",
    "+ 6.输出投影后的数据集。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 载入数据\n",
    "data = np.genfromtxt(\"data.csv\", delimiter=\",\")\n",
    "x_data = data[:,0]\n",
    "y_data = data[:,1]\n",
    "plt.scatter(x_data,y_data)\n",
    "plt.show()\n",
    "print(x_data.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 数据中心化\n",
    "def zeroMean(dataMat):\n",
    "    # 按列求平均，即各个特征的平均\n",
    "    meanVal = np.mean(dataMat, axis=0) \n",
    "    newData = dataMat - meanVal\n",
    "    return newData, meanVal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "newData,meanVal=zeroMean(data)  \n",
    "# np.cov用于求协方差矩阵，参数rowvar=0说明数据一行代表一个样本\n",
    "covMat = np.cov(newData, rowvar=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 协方差矩阵\n",
    "covMat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# np.linalg.eig求矩阵的特征值和特征向量\n",
    "eigVals, eigVects = np.linalg.eig(np.mat(covMat))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 特征值\n",
    "eigVals"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 特征向量\n",
    "eigVects"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对特征值从小到大排序\n",
    "eigValIndice = np.argsort(eigVals)\n",
    "eigValIndice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "top = 1\n",
    "# 最大的n个特征值的下标\n",
    "n_eigValIndice = eigValIndice[-1:-(top+1):-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_eigValIndice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 最大的n个特征值对应的特征向量\n",
    "n_eigVect = eigVects[:,n_eigValIndice]\n",
    "n_eigVect"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 低维特征空间的数据\n",
    "lowDDataMat = newData*n_eigVect\n",
    "lowDDataMat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 利用低纬度数据来重构数据\n",
    "reconMat = (lowDDataMat*n_eigVect.T) + meanVal\n",
    "reconMat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 载入数据\n",
    "data = np.genfromtxt(\"data.csv\", delimiter=\",\")\n",
    "x_data = data[:,0]\n",
    "y_data = data[:,1]\n",
    "plt.scatter(x_data,y_data)\n",
    "\n",
    "# 重构的数据\n",
    "x_data = np.array(reconMat)[:,0]\n",
    "y_data = np.array(reconMat)[:,1]\n",
    "plt.scatter(x_data,y_data,c='r')\n",
    "plt.show()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.neural_network import MLPClassifier\n",
    "from sklearn.datasets import load_digits\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import classification_report,confusion_matrix\n",
    "# 手写数字识别降维可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "digits = load_digits()#载入数据\n",
    "x_data = digits.data #数据\n",
    "y_data = digits.target #标签\n",
    "\n",
    "x_train,x_test,y_train,y_test = train_test_split(x_data,y_data) #分割数据1/4为测试数据，3/4为训练数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mlp = MLPClassifier(hidden_layer_sizes=(100,50) ,max_iter=500)\n",
    "mlp.fit(x_train,y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pca(dataMat,top):\n",
    "    # 数据中心化\n",
    "    newData,meanVal=zeroMean(dataMat) \n",
    "    # np.cov用于求协方差矩阵，参数rowvar=0说明数据一行代表一个样本\n",
    "    covMat = np.cov(newData, rowvar=0)\n",
    "    # np.linalg.eig求矩阵的特征值和特征向量\n",
    "    eigVals, eigVects = np.linalg.eig(np.mat(covMat))\n",
    "    # 对特征值从小到大排序\n",
    "    eigValIndice = np.argsort(eigVals)\n",
    "    # 最大的n个特征值的下标\n",
    "    n_eigValIndice = eigValIndice[-1:-(top+1):-1]\n",
    "    # 最大的n个特征值对应的特征向量\n",
    "    n_eigVect = eigVects[:,n_eigValIndice]\n",
    "    # 低维特征空间的数据\n",
    "    lowDDataMat = newData*n_eigVect\n",
    "    # 利用低纬度数据来重构数据\n",
    "    reconMat = (lowDDataMat*n_eigVect.T) + meanVal\n",
    "    # 返回低维特征空间的数据和重构的矩阵\n",
    "    return lowDDataMat,reconMat "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lowDDataMat,reconMat = pca(x_data,2)\n",
    "# 重构的数据\n",
    "x = np.array(lowDDataMat)[:,0]\n",
    "y = np.array(lowDDataMat)[:,1]\n",
    "plt.scatter(x,y,c='r')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lowDDataMat,reconMat = pca(x_data,3)\n",
    "from mpl_toolkits.mplot3d import Axes3D  \n",
    "x = np.array(lowDDataMat)[:,0]\n",
    "y = np.array(lowDDataMat)[:,1]\n",
    "z = np.array(lowDDataMat)[:,2]\n",
    "ax = plt.figure().add_subplot(111, projection = '3d') \n",
    "ax.scatter(x, y, z, c = y_data, s = 10) #点为红色三角形 \n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# sklearn-手写数字降维预测\n",
    "predictions = mlp.predict(x_test)\n",
    "print(classification_report(predictions, y_test))\n",
    "print(confusion_matrix(predictions, y_test))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pca = decomposition.PCA()\n",
    "pca.fit(x_data)\n",
    "pca.explained_variance_  # 方差\n",
    "pca.explained_variance_ratio_ # 方差占比\n",
    "variance = []\n",
    "for i in range(len(pca.explained_variance_ratio_)):\n",
    "    variance.append(sum(pca.explained_variance_ratio_[:i+1]))plt.plot(range(1,len(pca.explained_variance_ratio_)+1), variance)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pca = decomposition.PCA(whiten=True,n_components=0.8)\n",
    "pca.fit(x_data)\n",
    "x_train_pca = pca.transform(x_train)\n",
    "mlp = MLPClassifier(hidden_layer_sizes=(100,50) ,max_iter=500)\n",
    "mlp.fit(x_train_pca,y_train )\n",
    "x_test_pca = pca.transform(x_test)\n",
    "predictions = mlp.predict(x_test_pca)\n",
    "print(classification_report(predictions, y_test))\n",
    "print(confusion_matrix(predictions, y_test))"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}